use actix_web::{web, App, HttpResponse, HttpServer, Responder};
use serde::Deserialize;

#[actix_web::main]
async fn main() -> std::io::Result<()> {
    println!("Hello, world!");
    let server = HttpServer::new(|| {
        App::new()
            .route("/", web::get().to(index))
            .route("/gcd", web::post().to(gcd))
    });

    println!("Starting server at http://localhost:3000");
    let ser = server.bind("localhost:3000").expect("error binding server to address").run();
    ser.await
}


async fn index()-> impl Responder {
    HttpResponse::Ok().content_type("text/html").body(
        r#"
        <title>Chapter 1</title>
        <h1>Chapter 1</h1>
        <p>Hello from Rust!</p>
        <form action="/gcd" method="post">
        <input type="text" name="n"/>
        <input type="text" name="m"/>
        <button type="submit">Compute GCD</button>
        </form>
        "#,
    )
}

#[derive(Deserialize)]
struct GCDParameters {
    n: u64,
    m: u64,
}

async fn gcd(form: web::Form<GCDParameters>) -> impl Responder {
    if form.n == 0 || form.m == 0 {
        return HttpResponse::BadRequest()
            .content_type("text/html")
            .body("Computing the GCD with zero is boring.");
    } 

    let respone = format!(
        "The greatest common divisor of the numbers {} and {} is <b>{}</b>\n",
        form.n, form.m, gcd_deal(form.n, form.m)
    );

    HttpResponse::Ok().content_type("text/html").body(respone)
}

fn gcd_deal(mut n :u64, mut m: u64) -> u64 {
    assert!(n != 0 && m != 0);
    while m != 0 {
        if m< n {
            let t = m;
            m = n;
            n = t;
        }
        m = m % n;
    }
    n
}
